﻿using System;
using System.Linq;
using System.Web;
using System.Collections.Generic;

namespace Infrastructure.Crosscutting.NetFramework
{
    public class WebWorkContext : IWorkContext
    {
        #region private prop

        readonly HttpContextBase httpContext;

        Infrastructure.Crosscutting.Authorize.IUserRoleService userRoleService;

        Infrastructure.Crosscutting.Authorize.IUserService userService;

        Infrastructure.Crosscutting.Authorize.IMvcRolePermissionService rolePermissionService;

        Infrastructure.Crosscutting.Authorize.IMvcActionService actionService;

        Infrastructure.Crosscutting.Authorize.IMvcControllerService controllerService;

        Infrastructure.Crosscutting.Caches.ICacheService cacheService;

        Infrastructure.Crosscutting.Authorize.IRoleMenuService roleMenuService;

        #endregion

        public WebWorkContext(HttpContextBase ipowHttpContext,
            Infrastructure.Crosscutting.Authorize.IUserService user,
            Infrastructure.Crosscutting.Authorize.IUserRoleService userRole,
            Infrastructure.Crosscutting.Caches.ICacheService cache,
            Infrastructure.Crosscutting.Authorize.IMvcRolePermissionService rolePermission,
            Infrastructure.Crosscutting.Authorize.IMvcControllerService controllers,
            Infrastructure.Crosscutting.Authorize.IMvcActionService action,
            Infrastructure.Crosscutting.Authorize.IRoleMenuService roleMenu)
        {
            if (ipowHttpContext == null)
            {
                throw new ArgumentNullException("userService  is null");
            }
            if (user == null)
            {
                throw new ArgumentNullException("httpContext  is null");
            }
            if (userRole == null)
            {
                throw new ArgumentNullException("userRoleService  is null");
            }
            if (rolePermission == null)
            {
                throw new ArgumentNullException("rolePermissionService  is null");
            }
            if (action == null)
            {
                throw new ArgumentNullException("actionService  is null");
            }
            if (controllers == null)
            {
                throw new ArgumentNullException("controllerService  is null");
            }
            if (cache == null)
            {
                throw new ArgumentNullException("cacheService  is null");
            }
            if (roleMenu == null)
            {
                throw new ArgumentNullException("roleMenuService  is null");
            }
            httpContext = ipowHttpContext;
            userService = user;
            userRoleService = userRole;
            cacheService = cache;
            rolePermissionService = rolePermission;
            actionService = action;
            controllerService = controllers;
            roleMenuService = roleMenu;
        }

        public Domain.Entity.User CurrentUser
        {
            get
            {
                Domain.Entity.User user = null;
                if (httpContext != null && httpContext.Session != null)
                {
                    var temp = httpContext.Session[Infrastructure.Crosscutting.Comm.Service.ConstService.SessionNameCurrentUser] as Domain.Entity.User;
                    if (temp != null)
                    {
                        user = temp;
                    }
                }
                return user;
            }
        }

        public List<Domain.Entity.UserRole> UserRoleCache
        {
            get
            {
                List<Domain.Entity.UserRole> userRole = null;
                if (this.CurrentUser != null)
                {
                    var cacheUserRole = cacheService.Get(typeof(List<Domain.Entity.UserRole>).ToString() + this.CurrentUser.Guid)
                        as List<Domain.Entity.UserRole>;
                    if (cacheUserRole != null)
                    {
                        userRole = cacheUserRole;
                    }
                    else
                    {
                        userRole = userRoleService.GetUserRoleByUserId(CurrentUser.Id).ToList();
                        if (userRole != null)
                        {
                            cacheService.Insert(typeof(List<Domain.Entity.UserRole>).ToString() + this.CurrentUser.Guid, userRole,
                                Infrastructure.Crosscutting.Comm.Service.ConstService.SessionExpires,
                                 System.Web.Caching.CacheItemPriority.Default);
                        }
                    }
                }
                return userRole;
            }
        }

        public List<Domain.Entity.MvcAction> ActionCache
        {
            get
            {
                List<Domain.Entity.MvcAction> actions = null;
                if (this.CurrentUser != null)
                {
                    var cacheAction = cacheService.Get(typeof(List<Domain.Entity.MvcAction>).ToString() + this.CurrentUser.Guid)
                        as List<Domain.Entity.MvcAction>;
                    if (cacheAction == null)
                    {
                        if (this.UserRoleCache != null && this.UserRoleCache.Count > 0)
                        {
                            //用户的多个角色
                            //找到每个角色Id的所有能访问的action id list
                            var actionIdList = new List<int>();
                            foreach (var userRole in this.UserRoleCache)
                            {
                                var rolePermissionActionIdList = rolePermissionService
                                    .GetRolePermissionByRoleId(userRole.RoleId).Select(d => d.ActionId);
                                if (rolePermissionActionIdList.Any())
                                {
                                    actionIdList.AddRange(rolePermissionActionIdList);
                                }
                            }
                            //这个用户所有能访问的权限Id
                            //根据action id list 找到 action 表的权限列表
                            actionIdList = actionIdList.Distinct().ToList();
                            var actionList = actionService.GetList(actionIdList.AsQueryable());
                            if (actionList.Any())
                            {
                                actions = actionList.ToList();
                                cacheService.Insert(typeof(List<Domain.Entity.MvcAction>).ToString() + this.CurrentUser.Guid, actions,
                                    Infrastructure.Crosscutting.Comm.Service.ConstService.SessionExpires,
                                    System.Web.Caching.CacheItemPriority.Default);
                            }
                        }
                    }
                    else
                    {
                        actions = cacheAction;
                    }
                }
                return actions;
            }
        }

        public List<Domain.Entity.MvcController> ControllerCache
        {
            get
            {
                List<Domain.Entity.MvcController> controllers = null;
                if (this.CurrentUser != null)
                {
                    var cacheController = cacheService.Get(typeof(List<Domain.Entity.MvcController>).ToString() + this.CurrentUser.Guid)
                            as List<Domain.Entity.MvcController>;
                    if (cacheController == null)
                    {
                        if (this.ActionCache != null && this.ActionCache.Count > 0)
                        {
                            var controllerIdList = this.ActionCache.Select(e => e.ControllerId).Distinct();
                            var con = controllerService.GetList().Where(e => controllerIdList.Contains(e.Id));
                            if (con.Any())
                            {
                                controllers = con.ToList();
                                cacheService.Insert(typeof(List<Domain.Entity.MvcController>).ToString() + this.CurrentUser.Guid, controllers,
                                    Infrastructure.Crosscutting.Comm.Service.ConstService.SessionExpires,
                                    System.Web.Caching.CacheItemPriority.Default);
                            }
                        }
                    }
                    else
                    {
                        controllers = cacheController;
                    }
                }
                return controllers;
            }
        }

        public List<Domain.Entity.RoleMenu> RoleMenuCache
        {
            get
            {
                List<Domain.Entity.RoleMenu> roleMenu = null;
                if (this.UserRoleCache != null && this.UserRoleCache.Count > 0 && this.CurrentUser != null)
                {
                    var roleMenuCache = cacheService.Get(typeof(List<Domain.Entity.RoleMenu>).ToString() + this.CurrentUser.Guid)
                        as List<Domain.Entity.RoleMenu>;
                    if (roleMenuCache != null)
                    {
                        roleMenu = roleMenuCache;
                    }
                    else
                    {
                        roleMenu = new List<Domain.Entity.RoleMenu>();
                        foreach (var item in this.UserRoleCache)
                        {
                            //user role
                            var temp = roleMenuService.GetList().Where(e => e.RoleId == item.RoleId && e.State == true);
                            if (temp.Any())
                            {
                                roleMenu.AddRange(temp);
                            }
                        }
                        if (roleMenu != null && roleMenu.Any())
                        {
                            cacheService.Insert(typeof(List<Domain.Entity.RoleMenu>).ToString() + this.CurrentUser.Guid, roleMenu,
                                Infrastructure.Crosscutting.Comm.Service.ConstService.SessionExpires, System.Web.Caching.CacheItemPriority.Default);
                        }
                    }
                }
                return roleMenu;
            }
        }

        public bool IsAdmin
        {
            get
            {
                var isAdmin = false;
                if (this.CurrentUser != null && this.UserRoleCache != null)
                {
                    isAdmin = UserRoleCache.Where(e => e.RoleId == 1).Any();
                }
                return isAdmin;
            }
        }

        public bool IsOpenUser
        {
            get
            {
                var isOpenUser = false;
                if (this.CurrentUser != null && this.UserRoleCache != null)
                {
                    isOpenUser = this.UserRoleCache.Where(e => e.RoleId == 2 || e.RoleId == 1).Any();
                }
                return isOpenUser;
            }
        }

        public bool HasCurrentPermission(Type currentController, string currentAction)
        {
            var res = false;
            if (this.ControllerCache != null && this.ControllerCache.Count > 0 && this.ActionCache != null && this.ActionCache.Count > 0)
            {
                var con = this.ControllerCache.Where(e => e.AssemblyFullName.Trim() == currentController.FullName).FirstOrDefault();
                if (con != null)
                {
                    res = this.ActionCache.Where(e => e.ControllerId == con.Id && e.Name.ToLower() == currentAction.ToLower()).Any();
                }
            }
            return res;
        }

    }
}
